/*
 * Copyright (C) 2013 gujicheng
 * 
 * Licensed under the GPL License Version 2.0;
 * you may not use this file except in compliance with the License.
 * 
 * If you have any question, please contact me.
 * 
 *************************************************************************
 **                   Author information                                **
 *************************************************************************
 ** Email: gujicheng197@126.com                                         **
 ** QQ   : 29600731                                                     **
 ** Weibo: http://weibo.com/gujicheng197                                **
 *************************************************************************
 */
package com.libra.sinvoice

import android.media.AudioFormat
import android.media.AudioRecord
import android.media.MediaRecorder

import com.libra.sinvoice.Buffer.BufferData

class Record(private val mCallback: Callback?, frequence: Int, channel: Int, bits: Int, private val mBufferSize: Int) {

    var state: Int = 0
        private set

    private var mFrequence = 8000
    private var mChannel = CHANNEL_1
    private var mBits = BITS_8

    private var mChannelConfig = AudioFormat.CHANNEL_IN_MONO
    private var mAudioEncoding = AudioFormat.ENCODING_PCM_16BIT

    private var mListener: Listener? = null

    interface Listener {
        fun onStartRecord()

        fun onStopRecord()
    }

    interface Callback {
        fun getRecordBuffer(): BufferData?

        fun freeRecordBuffer(buffer: BufferData?)
    }

    init {
        state = STATE_STOP
        mFrequence = frequence
        mChannel = channel
        mBits = bits
    }

    fun setListener(listener: Listener) {
        mListener = listener
    }

    fun start() {
        if (STATE_STOP == state) {
            state = STATE_START

            when (mChannel) {
                CHANNEL_1 -> mChannelConfig = AudioFormat.CHANNEL_IN_MONO
                CHANNEL_2 -> mChannelConfig = AudioFormat.CHANNEL_IN_STEREO
            }

            when (mBits) {
                BITS_8 -> mAudioEncoding = AudioFormat.ENCODING_PCM_8BIT

                BITS_16 -> mAudioEncoding = AudioFormat.ENCODING_PCM_16BIT
            }

            val minBufferSize = AudioRecord.getMinBufferSize(mFrequence, mChannelConfig, mAudioEncoding)
            LogHelper.d(TAG, "minBufferSize:$minBufferSize")

            var record:AudioRecord? = AudioRecord(MediaRecorder.AudioSource.MIC, mFrequence, mChannelConfig, mAudioEncoding, mBufferSize)
            try {
                record!!.startRecording()
            } catch (e: Exception) {
                //
            }
            LogHelper.d(TAG, "record start")

            if (null != mCallback) {
                if (null != mListener) {
                    mListener!!.onStartRecord()
                }

                while (STATE_START == state) {
                    val data = mCallback.getRecordBuffer()
                    if (null != data) {
                        if (null != data.byteData) {
                            val bufferReadResult = record!!.read(data.byteData, 0, mBufferSize)
                            data.filledSize = bufferReadResult

                            mCallback.freeRecordBuffer(data)
                        } else {
                            // end of input
                            LogHelper.d(TAG, "get end input data, so stop")
                            break
                        }
                    } else {
                        LogHelper.d(TAG, "get null data")
                        break
                    }
                }

                if (null != mListener) {
                    mListener!!.onStopRecord()
                }
            }

            try {
                record!!.stop()
                record!!.release()
                record=null
            } catch (e: Exception) {
            }

            LogHelper.d(TAG, "record stop")
        }
    }

    fun stop() {
        if (STATE_START == state) {
            state = STATE_STOP
        }
    }

    companion object {
        private val TAG = "Record"
        private val STATE_START = 1
        private val STATE_STOP = 2

        val BITS_8 = 1
        val BITS_16 = 2

        val CHANNEL_1 = 1
        val CHANNEL_2 = 2
    }
}
